package com.demon.auto.controller;

import com.demon.auto.model.ApiResponseModel;
import com.demon.auto.model.dto.UserDto;
import com.demon.auto.model.entity.UserEntity;
import com.demon.auto.service.UserService;
import com.demon.auto.utils.JwtUtil;
import com.demon.auto.utils.LocalDateUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.Map;

/**
 * 登录接口
 *
 * @author huangrz
 * @version 1.0
 * @date 2025/02/13 14:29
 */
@RequestMapping("/api/auth")
@RestController
public class LoginController {

    /**
     *  access_token 有效期（2小时）
     */
    private static final long ACCESS_TOKEN_EXPIRATION = 7200000;
    /**
     *  refresh_token 有效期（3天）
     */
    private static final long REFRESH_TOKEN_EXPIRATION = 3 * 24 * 60 * 60 * 1000;

    @Autowired
    private UserService userService;

    @Autowired
    private PasswordEncoder passwordEncoder;

    /**
     * 登录
     *
     * @param user 用户信息
     * @return ResponseEntity<Map < String, Object>>
     */
    @RequestMapping("/login")
    public ApiResponseModel<UserDto> login(@Valid @RequestBody UserDto user) {
        UserEntity userEntity = userService.findByUsername(user.getUsername());
        if (userEntity == null) {
            return ApiResponseModel.error("用户不存在");
        }
        if (!passwordEncoder.matches(user.getPassword(), userEntity.getPassword())) {
            return ApiResponseModel.error("密码错误");
        }

        // 生成token
        Date expireDate = new Date(System.currentTimeMillis() + ACCESS_TOKEN_EXPIRATION);
        String token = JwtUtil.generateToken(userEntity.getUsername(), null, expireDate);

        LocalDateTime now = LocalDateTime.now();
        UserEntity updateEntity = new UserEntity()
                .setId(userEntity.getId())
                .setAccessToken(token)
                .setLastLoginTime(now);
        userService.updateById(updateEntity);

        UserDto userDto = new UserDto();
        BeanUtils.copyProperties(userEntity, userDto);
        userDto.setAccessToken(token)
                .setRefreshToken(JwtUtil.generateToken(userEntity.getUsername(), null, new Date(System.currentTimeMillis() + REFRESH_TOKEN_EXPIRATION)))
                .setLastLoginTime(now)
                .setTokenExpireDate(LocalDateUtil.dateToLocalDateTime(expireDate))
                .setPassword(null);
        return ApiResponseModel.ok("登录成功", userDto);
    }

    /**
     * 退出登录
     *
     * @param username 用户名
     * @return ResponseEntity<String>
     */
    @RequestMapping("/logout")
    public ApiResponseModel<Boolean> logout(String username) {
        if (StringUtils.isBlank(username)) {
            return ApiResponseModel.error("用户名不能为空");
        }
        // 清除用户认证信息
        SecurityContextHolder.clearContext();
        // 清空token
        return ApiResponseModel.ok("退出登录成功", userService.clearUserToken(new UserDto().setUsername(username)));
    }

    /**
     * 校验token是否有效
     *
     * @param token 签名
     * @return boolean
     */
    @RequestMapping("/validateToken")
    public ApiResponseModel<Boolean> validateToken(String token, String username) {
        if (StringUtils.isBlank(username)) {
            return ApiResponseModel.error("用户名不能为空");
        }
        // 清空token
        return ApiResponseModel.ok("校验token是否有效成功", JwtUtil.validateToken(token, username));
    }

    /**
     * token 续期
     * @param refreshToken token
     * @return ApiResponseModel<String>
     */
    @RequestMapping("/tokenRenewal")
    private ApiResponseModel<Map<String, Object>> tokenRenewal(String refreshToken) {
        if (StringUtils.isBlank(refreshToken)) {
            return ApiResponseModel.unauthorized("token为空！");
        }
        if (!JwtUtil.isTokenValid(refreshToken)) {
            return ApiResponseModel.unauthorized("token已过期！");
        }
        String username = JwtUtil.getUsernameByToken(refreshToken);
        if (StringUtils.isBlank(username)) {
            return ApiResponseModel.unauthorized("token无效！");
        }
        Date expireDate = new Date(System.currentTimeMillis() + ACCESS_TOKEN_EXPIRATION);
        String token = JwtUtil.generateToken(username, null, expireDate);

        return ApiResponseModel.ok("token 已续期", Map.of(
                "token", token,
                "expireDate", expireDate
        ));
    }

}
